package ru.spb.osll.myfit.server;

import java.io.FileNotFoundException;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Map;
import java.util.TreeMap;
import java.util.Vector;

import org.apache.log4j.Logger;

import ru.spb.osll.myfit.common.Include;
import ru.spb.osll.myfit.common.IncludeError;
import ru.spb.osll.myfit.common.Page;
import ru.spb.osll.myfit.common.PageElement;
import ru.spb.osll.myfit.common.Table;
import ru.spb.osll.myfit.common.TextParsingTools;
import ru.spb.osll.myfit.server.fixtureiterator.FileFactory;
import ru.spb.osll.myfit.server.handler.ContentHandler;
import ru.spb.osll.myfit.server.handler.PageLoader;
import ru.spb.osll.myfit.server.parser.PageParserUtils;
import ru.spb.osll.myfit.server.parser.RecursiveIncludeException;
import ru.spb.osll.myfit.server.templateloader.JarTableTemplateLoader;
import ru.spb.osll.myfit.server.templateloader.TableTemplateLoader;
import ru.spb.osll.myfit.util.StringUtils;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

@SuppressWarnings("serial")
public class CreateHelperServiceImpl extends RemoteServiceServlet implements
    ru.spb.osll.myfit.client.service.CreateHelperService {
  
  private Logger log = Logger.getLogger(getClass());
  private Converter m_converter = new Converter();
  private URLClassLoader m_classLoader;
  private TableTemplateLoader m_templateLoader;
  private TreeMap<String, String> m_templates;
  private ContentHandler m_contentHandler;
  private Map<String, Class< ? >> m_fixtureClasses;
  private ImportsPrinter m_importsPrinter;
  private Configurator m_configurator;

  public CreateHelperServiceImpl() {
    m_configurator = Configurator.getInstance();
    m_classLoader = new MyFitClassLoaderFactory(new FileFactory()).createClassLoader(m_configurator.getJars(),
        m_configurator.getFixtures());
    m_templateLoader = new JarTableTemplateLoader(m_configurator.getFixtures(), m_classLoader);
    m_fixtureClasses = m_templateLoader.getFixtureClasses();
    m_templates = new TreeMap<String, String>(new FixtureNameComparator());
    for (Map.Entry<String, Class< ? >> entry : m_fixtureClasses.entrySet()) {
      Class< ? > clazz = entry.getValue();
      m_templates.put(StringUtils.splitCamelCase(clazz.getSimpleName()), entry.getKey());
    }

    m_importsPrinter = new ImportsPrinter(m_fixtureClasses, m_configurator);
    m_contentHandler = new ContentHandler(m_importsPrinter, m_configurator.getRoot(), new PageLoader(m_configurator
        .getRoot()));
  }

  @Override
  public TreeMap<String, String> loadTemplates() throws Exception {
    TreeMap<String, String> map = new TreeMap<String, String>();
    map.putAll(m_templates);
    return map;
  }

  @Override
  public Table getTemplate(String name) throws Exception {
    Class< ? > clazz = m_fixtureClasses.get(name);
    Vector<String> rawTable = m_templateLoader.getTemplate(clazz.getName());
    Table table = m_contentHandler.getTable(rawTable, PageParserUtils.getTableStyle(clazz));
    return table;
  }

  public String convertWikiToHtml(String wikiText) {
    return m_converter.convertWikiToHtml(wikiText);
  }

  public PageElement loadInclude(String pagePath, String includePath) {
    log.info("Page path: " + pagePath);
    log.info("Include path: " + includePath);

    log.debug("Run loadInclude");

    Page page = null;

    ArrayList<String> allPath = new ArrayList<String>();
    allPath.add(pagePath);
    try {
      page = m_contentHandler.createInlcudePage(includePath, allPath);
      for (PageElement element : page.getElements()) {
        if (element instanceof Table) {
          setTableStyle((Table) element);
        }
      }
      return new Include(includePath, page);
    } catch (FileNotFoundException e) {
      return new IncludeError(includePath, m_contentHandler.createPageWithError(e.getMessage()));
    } catch (RecursiveIncludeException e) {
      String message = TextParsingTools.RECURSIVE_CALL + pagePath + " from the page " + e.getMessage();
      return new IncludeError(includePath, m_contentHandler.createPageWithError(message));
    }
  }

  private void setTableStyle(Table table) {
    String name = table.getData().get(0).get(0).getText();
    Class< ? > clazz = m_fixtureClasses.get(m_templates.get(name));
    table.setStyle(PageParserUtils.getTableStyle(clazz));
  }

}
